﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Threading;
using WorkFlow.Data.Model;

namespace WorkFlow.Data
{
    public class ScheduledTask
    {
        Timer tmrPick;
        WorkFlowController _WorkFlowController;
        DataManager _DataManager;
        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet =
    System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
        /// <summary>
        /// inerval time
        /// </summary>
        private int _PickTime = 3000;
        public ScheduledTask(WorkFlowController workFlowController, DataManager dataManager)
        {
            _WorkFlowController = workFlowController;
            _DataManager = dataManager;
            Start();
        }
        public void Start()
        {
            try
            {
                tmrPick = new System.Threading.Timer(new TimerCallback(tmrPick_Elapsed), null, _PickTime, Timeout.Infinite);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message.ToString(), ex);
            }
        }

        protected void tmrPick_Elapsed(object sender)
        {
            try
            {
                // 内存清理。
                if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                {
                    SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
                }
                List<ScheduledTaskEntity> scheduledTaskEntities = _DataManager.GetScheduledTasks("");
                foreach (ScheduledTaskEntity item in scheduledTaskEntities)
                {
                    try
                    {
                        DealTask(item);
                    }
                    catch (Exception ex)
                    {
                        LogHelper.WriteLog("ScheduledTask tmrPick_Elapsed2:", ex);
                    }
                }

            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("ScheduledTask tmrPick_Elapsed1:", ex);
            }
            finally
            {
                GC.Collect();
                tmrPick.Change(_PickTime, Timeout.Infinite);
            }
        }

        private void DealTask(ScheduledTaskEntity task)
        {
            List<TaskDetailEntity> taskDetailEntity = _DataManager.GetTaskDetails(task.ID);
            DateTime nextRunTime = DateTime.MaxValue;
            DateTime nowTime = DateTime.Now;

            if (taskDetailEntity.Count == 0)
            {
                switch (task.Type)
                {
                    case 1:
                        nextRunTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, task.Hour, task.Minute, task.Second);
                        break;
                    case 2:
                        int dayOfWeek = GetWeekByStr(nowTime.DayOfWeek);
                        nextRunTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day + (task.Day - dayOfWeek), task.Hour, task.Minute, task.Second);
                        break;
                    case 3:
                        nextRunTime = new DateTime(nowTime.Year, nowTime.Month, task.Day, task.Hour, task.Minute, task.Second);
                        break;
                    case 4:
                        nextRunTime = new DateTime(nowTime.Year, task.Month, task.Day, task.Hour, task.Minute, task.Second);
                        break;
                    case 5:
                        nextRunTime = nowTime;
                        break;
                    default:
                        break;
                }
            }
            else
            {
                TaskDetailEntity lastTaskEntity = taskDetailEntity[taskDetailEntity.Count - 1];
                DateTime lastTime = DateTime.Parse(lastTaskEntity.CreateTime);
                switch (task.Type)
                {
                    case 1:
                        nextRunTime = lastTime.AddDays(1);
                        break;
                    case 2:
                        nextRunTime = lastTime.AddDays(7);
                        break;
                    case 3:
                        nextRunTime = lastTime.AddMonths(1);
                        break;
                    case 4:
                        nextRunTime = lastTime.AddYears(1);
                        break;
                    case 5:
                        nextRunTime = lastTime.AddMonths(task.Month).AddDays(task.Day).AddHours(task.Hour).AddMinutes(task.Minute).AddSeconds(task.Second);
                        break;
                    default:
                        break;
                }
            }
            if (nowTime >= nextRunTime)
                StartWorkFlow(task);
        }

        private int GetWeekByStr(DayOfWeek dayOfWeek)
        {
            switch (dayOfWeek)
            {
                case DayOfWeek.Sunday:
                    return 7;
                case DayOfWeek.Monday:
                    return 1;
                case DayOfWeek.Tuesday:
                    return 2;
                case DayOfWeek.Wednesday:
                    return 3;
                case DayOfWeek.Thursday:
                    return 4;
                case DayOfWeek.Friday:
                    return 5;
                case DayOfWeek.Saturday:
                    return 6;
                default:
                    return -1;
            }
        }
        private void StartWorkFlow(ScheduledTaskEntity task)
        {
            Dictionary<string, string> workFlowDirectory = new Dictionary<string, string>();
            workFlowDirectory["WorkFlowName"] = task.WorkFlowName;
            workFlowDirectory["InitUser"] = "ByScheduledTask";
            string str = CommentTool.SerializeJson<Dictionary<string, string>>(workFlowDirectory);
            bool res = _WorkFlowController.RunWorkFlow(str);

            TaskDetailEntity taskDetailEntity = new TaskDetailEntity();
            taskDetailEntity.ParentID = task.ID;
            taskDetailEntity.Result = res ? 1 : 0;
            taskDetailEntity.CreateTime = DateTime.Now.ToString(WorkFlowTool.timeStyle);
            _DataManager.InsertTaskDetailEntity(taskDetailEntity);

        }

    }
}
